const num: number = 123;
const str: string = "";

interface SelectFunc {
  (pno: number, psize: number): Array<any>;
}
// 定义类型后该函数可以不需要描述返回值和参数类型
let func: SelectFunc = function (pno, psize) {
  return [
    { name: "小花", age: 18, sex: "女" },
    { name: "小白", age: 18, sex: "男" },
  ];
};

interface Config {
  entry: Array<any>;
  output: string;
  // 该属性可以动态定义非必要内容外的属性类型，使用后可以对原油对象扩展属性
  [str: string]: any;
}
let config: Config = { entry: [], output: "str" };

function test<T>(arg: T): T {
  return arg;
}

type Func = () => void;

const foo: Func = (): void => {};

interface FunctionInterface {
  // ()=> void
  aa: () => void;
}

// 两个不同类型的类型约束，需要用同一个 参数（action） 来区分，否则无法判断是哪个 , typeof不能判断。 item instanceof UP 官方可以判断,但本地是不行的。
// https://jkchao.github.io/typescript-book-chinese/typings/typeGuard.html#instanceof
type Search = {
  name: string;
  api: string;
  downLoadApi: string;
  action: "look";
};

type UP = {
  name: string;
  type: "deposit" | "trans" | "reach";
  action: "upload";
};

type Title = Search | UP;

const arr1: Array<UP | Search> = [
  { name: "1123", type: "deposit", action: "upload" },
  { name: "adfad", api: "1230", downLoadApi: "1213", action: "look" },
];

arr1.map((item) => {
  if (item.action === "look") {
    const { name, api, downLoadApi } = item;
  } else {
    const { name, type, action } = item;
  }
});

// 箭头函数泛型

const lamda = <T>(param: T) => {
  console.log(param);
};

lamda<number>(123123);

type Result<T extends () => any> = T extends () => Promise<infer U>
  ? U
  : ReturnType<T>;

interface A {
  name: string;
  type: "action";
}

interface B {
  age: number;
  type: "noAction";
}

type C = A | B;
const c: C = {
  name: "1231",
  type: "action",
};
// instanceof shi class 类型的校验
//  https://jkchao.github.io/typescript-book-chinese/typings/typeGuard.html#%E5%AD%97%E9%9D%A2%E9%87%8F%E7%B1%BB%E5%9E%8B%E4%BF%9D%E6%8A%A4
const a = (params: A | B) => {
  if ("name" in params) {
    console.log(params);
  }
  if ((params as A).name !== undefined) {
    console.log((params as A).name);
  }
  if (params.type === "noAction") {
    const { age } = params;
  }
};
// 判断类型
function foo1(params: C) {
  if ("name" in params) {
    console.log(params.name);
  }
  if ((<A>params).name) {
    console.log((<A>params).name);
  }
}

interface User {
  type: "user";
  name: string;
  age: number;
  occupation: string;
}

interface Admin {
  type: "admin";
  name: string;
  age: number;
  role: string;
}

export type Person = User | Admin;

// is is的用法
export const persons: Person[] = [
  {
    type: "user",
    name: "Max Mustermann",
    age: 25,
    occupation: "Chimney sweep",
  },
  { type: "admin", name: "Jane Doe", age: 32, role: "Administrator" },
  { type: "user", name: "Kate Müller", age: 23, occupation: "Astronaut" },
  { type: "admin", name: "Bruce Willis", age: 64, role: "World saver" },
];

export function isAdmin(person: Person): person is Admin {
  return person.type === "admin";
}

export function isUser(person: Person): person is User {
  return person.type === "user";
}

export function logPerson(person: Person) {
  let additionalInformation: string = "";
  if (isAdmin(person)) {
    additionalInformation = person.role;
  }
  if (isUser(person)) {
    additionalInformation = person.occupation;
  }
  console.log(` - ${person.name}, ${person.age}, ${additionalInformation}`);
}

console.log("Admins:");
persons.filter(isAdmin).forEach(logPerson);

console.log();

console.log("Users:");
persons.filter(isUser).forEach(logPerson);

// 箭头函数的泛型
const bar = <T>(x: T) => x;

export default {};

// typeof typeof 操作符可以用来获取一个变量或对象的类型。value 的类型（重点 复习了 keyof  和typeof）

const colors = {
  0: "#FFA306",
  1: 123,
  2: 23,
};
type AB = typeof colors;

const ab: AB = {
  0: "2",
  1: 1,
  2: 1,
};

// 在类型中庸keyof 获取key 的类型 也就是 0|1|2
type BC = keyof AB;

interface Foo<T = any> {
  api: () => T;
  renderHeader: (params: T) => any;
}
/** 泛型必须要用在函数上。 */
const obj = <T>(params: Foo<T>) => {};

// 不传递就相当于使用默认值
// const obj = (params: Foo) => {};

const tempApi = () => [1, 2];
obj({
  api: tempApi,
  renderHeader: (data) => data,
});
